package com.hxzy.common.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.hxzy.common.constans.RedisConstans;
import com.hxzy.controller.vue.login.resp.AdminLoginResp;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author wy
 * @Description 一个用户可以登录多次令牌操作
 * @Date 2023/8/29 14:04
 * @Version 1.0
 */
@Log4j2
@Component
public class MultipleTokenService implements JwtTokenService<AdminLoginResp>{

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public String createJwtToken(AdminLoginResp resp) {
        resp.setUuid(UUID.randomUUID().toString());

        this.refreshToken(resp);

        //把值加密成jwt
        Map<String, Object> claims = new HashMap<>();
        claims.put(UUID_KEY, resp.getUuid());
        claims.put(USER_TYPE, resp.getPermissions().get(0));

        //生成jwt
        String jwtToken = JWTUtil.createToken(claims,  JWT_SECURITY.getBytes());

        return jwtToken;
    }

    /**
     *  令牌还有20分钟就结束了，为这个令牌再次赋值为1小时
     * @param resp
     */
    @Override
    public void verifyToken(AdminLoginResp resp) {
        //剩余时间20分钟
        long twenty_minutes=1000L*60*20;
        long expireTime = resp.getExpired().getTime();
        long currentTime = System.currentTimeMillis();
        //redis过期时间<=20分钟，快过期了
        if (expireTime - currentTime <= twenty_minutes) {
            refreshToken(resp);
        }
    }

    /**
     * 把数据存储到redis中
     * @param resp 登录信息
     */
    @Override
    public void refreshToken(AdminLoginResp resp) {
        resp.setExpired(new Date(System.currentTimeMillis()+ (RedisConstans.ADMIN_TOKEN_EXPIRED_MINTUES * 60L*1000)));

        String redisKey=this.getReidsKey(resp.getPermissions().get(0),resp.getUuid());

        this.redisTemplate.opsForValue().set(redisKey,resp,RedisConstans.ADMIN_TOKEN_EXPIRED_MINTUES, TimeUnit.MINUTES);

    }

    /**
     * 根据类型得到redisKey
     * @param type 类型
     * @param value 值
     * @return
     */
    @Override
    public String getReidsKey(String type,String value){
        String redisKey="";
        if(type.equals(ADMIN)){
            redisKey=RedisConstans.getRedisKey(RedisConstans.ADMIN_TOKEN_KEY,value);
        }else{
            redisKey=RedisConstans.getRedisKey(RedisConstans.MERCHANDISER_TOKEN_KEY,value);
        }
        return redisKey;
    }

    /**
     * 获取用户身份信息
     * @param jwtToken
     * @return
     */
    @Override
    public AdminLoginResp getLoginResp(String jwtToken) {
        //jwt令牌
        try {
            boolean isTrue = JWTUtil.verify(jwtToken, JWT_SECURITY.getBytes(StandardCharsets.UTF_8));
            if (isTrue) {
                //解析令牌中的值
                JWT jwt = JWTUtil.parseToken(jwtToken);
                //uuid
                String value=jwt.getPayload(UUID_KEY).toString();
                //用户类型
                String type=jwt.getPayload(USER_TYPE).toString();

                String redisKey=this.getReidsKey(type,value);
                Object redisValue = this.redisTemplate.opsForValue().get(redisKey);

                if(Objects.nonNull(redisValue)){
                   return (AdminLoginResp) redisValue;
                }
                return null;
            }
        } catch (Exception e) {
            log.error(e);
        }
        return null;
    }

    /**
     * 从redis中移出用户身份信息
     * @param resp
     */
    @Override
    public void delLoginUser(AdminLoginResp resp) {
        String redisKey=this.getReidsKey(resp.getPermissions().get(0),resp.getUuid());
        this.redisTemplate.delete(redisKey);
    }
}
